package a13;

import org.springframework.cglib.core.Signature;
import org.springframework.cglib.reflect.FastClass;

import java.lang.reflect.InvocationTargetException;

/**
 * (感觉了解即可：)
 * 已经知道，cglib中有三种调用方式，第二种和第三种是都是通过MethodProxy，不是反射调用的。这里说第二种:
 * methodProxy.invoke(target, objects);它的原理是怎么样的呢？
 * 大概原理就是： 会生成一个继承了FastClass的类，methodProxy.invoke(target, objects)最终会调用到这个里面来，
 * 而这个类里面不是反射调用，而是直接调用的。那这个类长什么样呢？这个类也是不经过编译阶段直接字节码生成的，这里只是简单
 * 的模拟下它内部的内容是什么样的。
 *
 *
 */
public class TargetFastClass{

    static Signature s0 = new Signature("save", "()V");
    static Signature s1 = new Signature("save", "(I)V");
    static Signature s2 = new Signature("save", "(J)V");


    /**
     * MethodProxy通过这个方法来获取调用的方法的index
     * signature 包括方法名字、参数返回值
     */
    public int getIndex(Signature signature) {
        if (s0.equals(signature)) {
            return 0;
        } else if (s1.equals(signature)) {
            return 1;
        } else if (s2.equals(signature)) {
            return 2;
        }
        return -1;
    }

    /**
     * 得index后，利用用户传入的Target和参数来调用原始的方法。
     * @param index
     * @param target 用户传入的Target对象
     * @param args
     * @return
     * @throws InvocationTargetException
     */
    public Object invoke(int index, Object target, Object[] args) throws InvocationTargetException {
        if (index == 0) {
            ((Target) target).save();
            return null;
        } else if (index == 1) {
            ((Target) target).save((int) args[0]);
            return null;
        } else if (index == 2) {
            ((Target) target).save((long) args[0]);
            return null;
        } else {
            throw new RuntimeException("无此方法");
        }
    }

    public static void main(String[] args) throws InvocationTargetException {
        TargetFastClass fastClass = new TargetFastClass();
        int index = fastClass.getIndex(new Signature("save", "(I)V"));
        System.out.println(index);
        fastClass.invoke(index, new Target(), new Object[]{100});
    }


}
